# -*- coding: utf-8 -*-

from abc import ABCMeta, abstractmethod
import threading

from django.conf import settings as global_settings

from financial_daily.utils import WordSegUtils
from basic_info.models import Stock, Institute, Industry

class TermProcessor:
    __metaclass__ = ABCMeta

    TITLE = global_settings.REDIS_DATA_ATTRIBUTE['title']
    CONTENT = global_settings.REDIS_DATA_ATTRIBUTE['content']

    @abstractmethod
    def process():
        return NotImplemented

    @abstractmethod
    def set_current_doc_id(self, doc_id, **args):
        return NotImplemented

class StockNameProcessor(TermProcessor):

    '''
    将term中涉及的股票名称抽取统计
    '''
  
    # 多实例公用STOCK_NAME_SET和INSTITUTION_NAME_MAP
    stock_name_map_initialized = False
    lock_obj = threading.Lock()

    STOCK_NAME_SET = None
    INSTITUTION_NAME_MAP = None
    def __init__(self):
        
        with self.lock_obj:
            if not self.stock_name_map_initialized: 
                self.STOCK_NAME_CODE_SET = Stock.get_stock_name_set()
                self.INSTITUTION_NAME_MAP = Institute.get_institute_name_map()
                self.stock_name_map_initialized = True

        # 当前正在处理文档的doc_id
        self.current_doc_id = None
        # 股票名出现次数映射
        self.stock_name_occ_map = dict()

    def set_current_doc_id(self, doc_id, **args):
        self.current_doc_id = doc_id
        # 重置occ映射
        self.stock_name_occ_map.clear()
  
    def process(self, term):
        if self.current_doc_id == None:
            raise Exception('Current doc id was not set yet.')

        if term in self.STOCK_NAME_CODE_SET and not self.INSTITUTION_NAME_MAP.has_key(term):
            # term为个股名称且非机构名称
            if self.stock_name_occ_map.has_key(term):
                self.stock_name_occ_map[term] += 1
            else:
                self.stock_name_occ_map[term] = 0
 
    def get_entity_list_from_current_doc(self):
        stock_list = []
        for stock, occ_count in self.stock_name_occ_map.iteritems():
            if occ_count >= global_settings.STOCK_NAME_OCCURRENCE_THRESHOLD:
                stock_list.append(stock)
        return stock_list
  
class InstitutionNameProcessor(StockNameProcessor):

    '''
    将term中涉及的机构名称抽取统计
    '''
    def __init__(self):
      
        StockNameProcessor.__init__(self)
        # 当前正在处理券商名称
        self.current_institute = None
        self.stock_doc_id_map = dict()

    def set_current_doc_id(self, doc_id, **args):
        # 分词，寻找其中的券商名称
        if self.TITLE in args:
            found_name = False
            seg_tokens = WordSegUtils.word_segment_phrase(args[self.TITLE]) #粗粒度
            for token in seg_tokens:
                term = token[global_settings.WORD_SEG_LEX_TEXT]
                if self.INSTITUTION_NAME_MAP.has_key(term):
                    self.current_doc_id = doc_id
                    self.current_institute = self.INSTITUTION_NAME_MAP[term]
                    found_name = True
                    break;
            if not found_name:
                self.current_doc_id = None
    
    def get_stock_doc_id_map(self):
        return self.stock_doc_id_map

    def process(self, term, sent_id):
        if self.current_doc_id == None:
            return

        if term in self.STOCK_NAME_CODE_SET and term != self.current_institute: #这支股票名称非券商名
            if self.stock_doc_id_map.has_key(term):
                current_stock = self.stock_doc_id_map[term]
                if not current_stock.has_key(
                        (self.current_doc_id, self.current_institute)):
                    self.current_stock[(self.current_doc_id, self.current_institute)] = sent_id
            else:
                self.stock_doc_id_map[term] = {(self.current_doc_id, self.current_institute): sent_id}

class IndustryNameProcessor(StockNameProcessor):
  
    INDUSTRY_NAME_SET = set()
    '''
    将term中涉及的行业名称抽取统计
    '''
    def __init__(self):
      
        StockNameProcessor.__init__(self)
        self.INDUSTRY_NAME_SET= Industry.get_industry_name_set()

    def process(self, term):
        if self.current_doc_id == None:
            raise Exception('Current doc id was not set yet.')

        if term in self.INDUSTRY_NAME_SET:
            if self.stock_doc_id_map.has_key(term):
                self.stock_doc_id_map[term].add(self.current_doc_id)
            else:
                self.stock_doc_id_map[term] = set([self.current_doc_id])

